package com.loklok.code.confuse.util;

import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;

import java.util.*;

public class NestedClassCollector {

    /**
     * 判断一个类是否是允许收集的类型（属于指定包路径下且不是 JDK 类或包装类）
     */
    private static boolean isAllowedType(PsiClass psiClass, String packagePrefix) {
        String qualifiedName = psiClass.getQualifiedName();
        if (qualifiedName == null) {
            return false;
        }

        // 排除 JDK 类
        if (qualifiedName.startsWith("java.") ||
                qualifiedName.startsWith("javax.") ||
                qualifiedName.startsWith("jdk.")) {
            return false;
        }

        // 排除包装类型
        if (isJdkWrapperType(qualifiedName) || psiClass.isEnum()) {
            return false;
        }

        // 只保留指定包路径下的类
        return qualifiedName.startsWith(packagePrefix);
    }

    /**
     * 判断是否为 JDK 包装类型
     */
    private static boolean isJdkWrapperType(String className) {
        return Set.of(
                "java.lang.String",
                "java.lang.Integer", "java.lang.Long", "java.lang.Boolean",
                "java.lang.Double", "java.lang.Float", "java.lang.Short",
                "java.lang.Byte", "java.lang.Character"
        ).contains(className);
    }

    /**
     * 获取指定类及其字段中引用的所有非内部类（递归）
     *
     * @param psiClass    起始类
     * @param visited     已处理的类集合（防止重复和循环引用）
     * @param packagePrefix 只保留以此包路径开头的类（如 "groot."）
     * @return 所有引用的非内部类
     */
    public static Set<PsiClass> collectAllReferencedClasses(@NotNull PsiClass psiClass,
                                                            @NotNull Set<PsiClass> visited,
                                                            @NotNull String packagePrefix) {
        if (visited.contains(psiClass)) {
            return Collections.emptySet();
        }

        visited.add(psiClass);

        Set<PsiClass> result = new LinkedHashSet<>();
        result.add(psiClass);

        // 处理当前类的泛型参数（如 List<UserVO> 中的 UserVO）
        PsiType type = JavaPsiFacade.getElementFactory(psiClass.getProject())
                .createType(psiClass);
        collectFromType(type, result, visited, packagePrefix);

        // 直接从 getSuperTypes() 获取完整泛型类型（如 FrontEndPagingResponse<UserVO>）
        for (PsiType superType : psiClass.getSuperTypes()) {
            if (superType instanceof PsiClassType) {
                collectFromType(superType, result, visited, packagePrefix);

                // 递归处理父类本身（如 FrontEndPagingResponse）
                PsiClass superClass = ((PsiClassType) superType).resolve();
                if (superClass != null && isAllowedType(superClass, packagePrefix)) {
                    result.addAll(collectAllReferencedClasses(superClass, visited, packagePrefix));
                }
            }
        }

        // 收集接口
        for (PsiClass intf : psiClass.getInterfaces()) {
            if (isAllowedType(intf, packagePrefix)) {
                result.addAll(collectAllReferencedClasses(intf, visited, packagePrefix));
            }
        }

        // 遍历字段
        for (PsiField field : psiClass.getFields()) {
            PsiType fieldType = field.getType();
            collectFromType(fieldType, result, visited, packagePrefix);
        }

        // 处理内部类（如果有）
        if (psiClass.getContainingFile() instanceof PsiClassOwner) {
            PsiClassOwner owner = (PsiClassOwner) psiClass.getContainingFile();
            for (PsiClass innerClass : owner.getClasses()) {
                if (!innerClass.isInterface() && !innerClass.hasModifierProperty(PsiModifier.STATIC)) {
                    continue;
                }
                result.addAll(collectAllReferencedClasses(innerClass, visited, packagePrefix));
            }
        }

        return result;
    }


    /**
     * 从类型中提取类并递归收集
     */
    private static void collectFromType(PsiType type,
                                        Set<PsiClass> result,
                                        Set<PsiClass> visited,
                                        String packagePrefix) {
        if (type instanceof PsiClassType) {
            PsiClass resolveClass = ((PsiClassType) type).resolve();
            if (resolveClass != null && isAllowedType(resolveClass, packagePrefix)) {
                result.addAll(collectAllReferencedClasses(resolveClass, visited, packagePrefix));
            }

            // 处理泛型参数（如 List<PostContentVO> 中的 PostContentVO）
            for (PsiType paramType : ((PsiClassType) type).getParameters()) {
                collectFromType(paramType, result, visited, packagePrefix);
            }
        } else if (type instanceof PsiArrayType) {
            collectFromType(((PsiArrayType) type).getComponentType(), result, visited, packagePrefix);
        } else if (type instanceof PsiWildcardType) {
            PsiType bound = ((PsiWildcardType) type).getBound();
            if (bound != null) {
                collectFromType(bound, result, visited, packagePrefix);
            }
        } else if (type instanceof PsiIntersectionType) {
            for (PsiType t : ((PsiIntersectionType) type).getConjuncts()) {
                collectFromType(t, result, visited, packagePrefix);
            }
        } else if (type instanceof PsiDisjunctionType) {
            for (PsiType t : ((PsiDisjunctionType) type).getDisjunctions()) {
                collectFromType(t, result, visited, packagePrefix);
            }
        } else if (type instanceof PsiDiamondType) {
            PsiType deepComponentType = type.getDeepComponentType();
            collectFromType(deepComponentType, result, visited, packagePrefix);
        }
    }

    /*private static void collectFromType(PsiType type,
                                        Set<PsiClass> result,
                                        Set<PsiClass> visited,
                                        String packagePrefix) {
        if (type instanceof PsiClassType) {
            PsiClass resolveClass = ((PsiClassType) type).resolve();
            if (resolveClass != null && isAllowedType(resolveClass, packagePrefix)) {
                result.addAll(collectAllReferencedClasses(resolveClass, visited, packagePrefix));
            }

            // 处理泛型参数（如 List<PostContentVO> 中的 PostContentVO）
            for (PsiType paramType : ((PsiClassType) type).getParameters()) {
                collectFromType(paramType, result, visited, packagePrefix);
            }

        } else if (type instanceof PsiArrayType) {
            collectFromType(((PsiArrayType) type).getComponentType(), result, visited, packagePrefix);

        } else if (type instanceof PsiWildcardType) {
            PsiType bound = ((PsiWildcardType) type).getBound();
            if (bound != null) {
                collectFromType(bound, result, visited, packagePrefix);
            }

        } else if (type instanceof PsiIntersectionType) {
            for (PsiType t : ((PsiIntersectionType) type).getConjuncts()) {
                collectFromType(t, result, visited, packagePrefix);
            }

        } else if (type instanceof PsiDisjunctionType) {
            for (PsiType t : ((PsiDisjunctionType) type).getDisjunctions()) {
                collectFromType(t, result, visited, packagePrefix);
            }

        } else if (type instanceof PsiDiamondType) {
            PsiType deepComponentType = type.getDeepComponentType();
            collectFromType(deepComponentType, result, visited, packagePrefix);
        }
    }*/
}
